package com.zjun.demo.experimentaldemo.udp.server

import android.util.Log
import com.zjun.demo.experimentaldemo.udp.call.HOTSPOT_HOST_PORT
import com.zjun.demo.experimentaldemo.udp.call.ICallBackMsg
import com.zjun.demo.experimentaldemo.udp.call.IServerLaunchCallBack
import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
import io.netty.channel.EventLoopGroup
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioDatagramChannel

class UdpServer private constructor() {

    private var bootstrap: Bootstrap? = null

    private var worker: EventLoopGroup? = null

    private var channel:Channel? = null

    var iServerLaunchCallBack: IServerLaunchCallBack? = null

    private var iCallBackMsg: ICallBackMsg? = null

    fun setCallBackMsgListener(iCallBackMsg: ICallBackMsg){
        if(bootstrap !=null){
            throw Exception("需要在初始化前设置")
        }
        this.iCallBackMsg = iCallBackMsg
    }

    fun start() {
        stop()
        worker = NioEventLoopGroup()
        bootstrap = Bootstrap()
            .group(worker)
            .channel(NioDatagramChannel::class.java)
            .option(ChannelOption.SO_BROADCAST, true)
            .option(ChannelOption.SO_REUSEADDR, true)
            .handler(object : ChannelInitializer<Channel>() {

                @Throws(Exception::class)
                override fun initChannel(ch: Channel) {
                    Log.i(TAG, "客户端已启动")
                    channel = ch
                    ch.pipeline().addLast(UdpServerHandler(iCallBackMsg))
                    iServerLaunchCallBack?.launchSuccess(ch)
                }

                override fun channelInactive(ctx: ChannelHandlerContext) {
                    super.channelInactive(ctx)
                    iServerLaunchCallBack?.launchFail(ctx)
                }

            })
        bootstrap!!.bind(HOTSPOT_HOST_PORT).sync().channel().closeFuture().sync()
    }

    private fun stop() {
        if(worker!=null){
            worker!!.shutdownGracefully()
            worker = null
        }
        if (channel != null) {
            channel!!.disconnect()
            channel!!.close()
            channel = null
        }
        bootstrap = null
    }

    fun destroy(){
        iCallBackMsg = null
        iServerLaunchCallBack = null
        stop()
    }
    companion object {

        private val TAG = UdpServer::class.java.simpleName

        var instance = UdpServer()

    }
}
